#ifndef CONVENT_HTMLPARSER_
#define CONVENT_HTMLPARSER_

#include <iconv.h>

#include <string>
#include <iostream>
using namespace std;


string ToUTF8(const string &source, string charset, int c = 0)
{
    string result;
	const char *from = charset.c_str();
	const char *to = "UTF-8";
	const char *src = source.c_str();
	size_t len = source.length();


	iconv_t cd;

	char *pinbuf = const_cast< char* >(src);
	size_t inbytesleft = len;
	char *poutbuf = NULL;
	size_t buf_size = 2 * len;
	size_t outbytesleft = buf_size;

	char *dst = NULL;
	size_t retbytes = 0;
	int done = 0;
	int errno_save = 0;

	if ((iconv_t)-1 == (cd = iconv_open(to, from))) 
	{
  		return source;
	}

	dst = new char[buf_size];

	while(inbytesleft > 0 && !done)  
	{
  		poutbuf = dst;
  		outbytesleft = buf_size;
  
  		retbytes = iconv(cd, &pinbuf, &inbytesleft, &poutbuf, &outbytesleft);
  		errno_save = errno;
  
  		if (dst != poutbuf)  {// we have something to write
   			result.append(dst, poutbuf-dst);
  		} 
  
  		if (retbytes != (size_t)-1) 
		{
   			poutbuf = dst;
   			outbytesleft = buf_size;
   			(void)iconv(cd, NULL, NULL, &poutbuf, &outbytesleft);
   
   			if (dst != poutbuf) 
			{// we have something to write
    			result.append(dst, poutbuf-dst);
   			}
   
   			errno_save = 0;
   			break;
  		}	
  
  
  
  		switch(errno_save)  {
  		case E2BIG:
   			break;
  		case EILSEQ:
   			if (c) {
    			errno_save = 0;
    			inbytesleft = len-(pinbuf-src); // forward one illegal byte
    			inbytesleft--;
				*pinbuf = ' ';
    			pinbuf++;
    			break;
   			}
   
   			done = 1;
   			break;
  		case EINVAL:
   			done = 1;
  	 		break;
  		default:
   			done = 1;
   			break; 
  		}
  
	}

	delete[] dst;
	iconv_close(cd);

	return result;
}

//r==0 success
//r==1 error
string ToUTF82(const string &source, string charset, int &r, int c = 0)
{
	r = 0;

    string result;
	const char *from = charset.c_str();
	const char *to = "UTF-8";
	const char *src = source.c_str();
	size_t len = source.length();


	iconv_t cd;

	char *pinbuf = const_cast< char* >(src);
	size_t inbytesleft = len;
	char *poutbuf = NULL;
	size_t buf_size = 2 * len;
	size_t outbytesleft = buf_size;

	char *dst = NULL;
	size_t retbytes = 0;
	int done = 0;
	int errno_save = 0;

	if ((iconv_t)-1 == (cd = iconv_open(to, from))) 
	{
  		return source;
	}

	dst = new char[buf_size];

	while(inbytesleft > 0 && !done)  
	{
  		poutbuf = dst;
  		outbytesleft = buf_size;
  
  		retbytes = iconv(cd, &pinbuf, &inbytesleft, &poutbuf, &outbytesleft);
  		errno_save = errno;
  
  		if (dst != poutbuf)  {// we have something to write
   			result.append(dst, poutbuf-dst);
  		} 
  
  		if (retbytes != (size_t)-1) 
		{
   			poutbuf = dst;
   			outbytesleft = buf_size;
   			(void)iconv(cd, NULL, NULL, &poutbuf, &outbytesleft);
   
   			if (dst != poutbuf) 
			{// we have something to write
    			result.append(dst, poutbuf-dst);
   			}
   
   			errno_save = 0;
   			break;
  		}	
  
  
  
  		switch(errno_save)  {
  		case E2BIG:
   			break;
  		case EILSEQ:
			r = 1;
   			done = 1;
   			break;
  		case EINVAL:
   			done = 1;
  	 		break;
  		default:
   			done = 1;
   			break; 
  		}
  
	}

	delete[] dst;
	iconv_close(cd);

	return result;
}

#endif
